package com.knowledge.common.utils;


import java.io.*;
import java.text.ParseException;
import java.util.List;
import java.util.Map;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson2.JSON;
import com.aliyun.docmind_api20220711.models.*;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.docmind_api20220711.Client;
import com.aliyun.teautil.models.RuntimeOptions;
import lombok.extern.slf4j.Slf4j;


/**
 * 文件解析工具类
 * 支持多种文件格式的内容提取
 *
 * @author knowledge
 */
@Slf4j
public class AliYunFileParserUtils {

    // 阿里云短信配置信息
    private static final String accessKeyId = "LTAI5tFSpEuFVeCj8CVqGFCU";
    private static final String accessKeySecret = "Vsvs9UcVfF1kiBL9LDthKg5WwP9aQS";


    //(第一步)调用文档解析（大模型版）异步提交服务SubmitDocParserJob接口
    public static String submitDocParserJob(File file, String fileName) throws Exception {
        String parseId = "";
        // 使用默认凭证初始化Credentials Client。
//        com.aliyun.credentials.Client credentialClient = new com.aliyun.credentials.Client();
        Config config = new Config()
                // 通过credentials获取配置中的AccessKey ID
                .setAccessKeyId(accessKeyId)
                // 通过credentials获取配置中的AccessKey Secret
                .setAccessKeySecret(accessKeySecret);
        // 访问的域名，支持ipv4和ipv6两种方式，ipv6请使用docmind-api-dualstack.cn-hangzhou.aliyuncs.com
        config.endpoint = "docmind-api.cn-hangzhou.aliyuncs.com";
        Client client = new Client(config);
        // 创建RuntimeObject实例并设置运行参数
        // 创建RuntimeObject实例并设置运行参数
        RuntimeOptions runtime = new RuntimeOptions();

        SubmitDocParserJobAdvanceRequest advanceRequest = new SubmitDocParserJobAdvanceRequest();
        advanceRequest.fileUrlObject = new FileInputStream(file);
        advanceRequest.fileName = fileName;
        // 发起请求并处理应答或异常。
        SubmitDocParserJobResponse response = client.submitDocParserJobAdvance(advanceRequest, runtime);
        if (response.getStatusCode() == 200) {
            // 错误编码
            String code = response.getBody().getCode();
            // 错误信息
            String message = response.getBody().getMessage();
            if (StringUtils.isNotEmpty(code)) {
                throw new Exception("文档提交任务错误码:" + code + "错误信息：" + message);
            }
            parseId = response.getBody().getData().getId();
            System.out.println("任务ID：" + parseId);
        } else {
            System.out.println("错误码:" + response.getBody().getCode());
            throw new Exception("文档提交任务错误码:" + response.getBody().getCode());
        }
        return parseId;
    }

    /**
     * 提交网址文件进行文档解析
     *
     * @param fileUrl  文件的公网可访问URL
     * @param fileName 文件名（可选）
     * @return 解析任务ID
     * @throws Exception 异常
     */
    public static String submitDocParserJobByUrl(String fileUrl, String fileName) throws Exception {
        String parseId = "";

        Config config = new Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);
        config.endpoint = "docmind-api.cn-hangzhou.aliyuncs.com";
        Client client = new Client(config);

        SubmitDocParserJobRequest request = new SubmitDocParserJobRequest();
        request.fileUrl = fileUrl;
        request.fileName = fileName;

        SubmitDocParserJobResponse response = client.submitDocParserJob(request);
        if (response.getStatusCode() == 200) {
            // 错误编码
            String code = response.getBody().getCode();
            // 错误信息
            String message = response.getBody().getMessage();
            if (StringUtils.isNotEmpty(code)) {
                throw new Exception("文档提交任务错误码:" + code + "错误信息：" + message);
            }
            parseId = response.getBody().getData().getId();
            System.out.println("任务ID：" + parseId);
        } else {
            System.out.println("错误码:" + response.getBody().getCode());
            throw new Exception("文档提交任务错误码:" + response.getBody().getCode());
        }
        return parseId;
    }

    //(第二步)调用结果查询类API
    public static String getClJg(String parseId) throws Exception {
        String parseStatus = "";
        // 调用接口时，程序直接访问凭证，读取您的访问密钥（即AccessKey）并自动完成鉴权。
        // 运行本示例前，请先完成步骤二：配置身份认证。
        // 本示例使用默认配置文件方式，通过配置Credentials文件创建默认的访问凭证。
        // 使用默认凭证初始化Credentials Client。
        Config config = new Config()
                // 通过credentials获取配置中的AccessKey ID
                .setAccessKeyId(accessKeyId)
                // 通过credentials获取配置中的AccessKey Secret
                .setAccessKeySecret(accessKeySecret);
        // 访问的域名，支持IPv4和IPv6两种方式，IPv6请使用docmind-api-dualstack.cn-hangzhou.aliyuncs.com。
        config.endpoint = "docmind-api.cn-hangzhou.aliyuncs.com";
        Client client = new Client(config);
        QueryDocParserStatusRequest resultRequest = new QueryDocParserStatusRequest();
        resultRequest.id = parseId;
        QueryDocParserStatusResponse response = client.queryDocParserStatus(resultRequest);
        if (response.getStatusCode() == 200) {
            QueryDocParserStatusResponseBody body = response.getBody();
            QueryDocParserStatusResponseBody.QueryDocParserStatusResponseBodyData data = body.getData();
            String status = data.getStatus();
            parseStatus = status;
            //订单状态Status类型：
            //
            //Init：订单处于待处理队列中。
            //
            //Processing: 正在解析处理。
            //
            //success：文件处理成功，此时NumberOfSuccessfulParsing将不再变化。
            //
            //Fail：文件处理失败。
            if ("success".equals(status)) {
                System.out.println("文件处理成功");
            } else if ("Fail".equals(status)) {
                System.out.println("文件处理失败");
            } else if ("Init".equals(status)) {
                System.out.println("文件处理中");
            } else if ("Processing".equals(status)) {
                System.out.println("正在解析处理");
            }

        }
        return parseStatus;
    }

    // (第三步)调用文档解析（大模型版）结果获取服务GetDocParserResult接口
    //使用GetDocParserResult接口，意味着需要进行多次结果的查询（例如 [LayoutNum,LayoutNum+LayoutStepSize]
    // 获取 0～100，100～200块内容），同时能在长文档解析时，能提前获取已解析完内容。
//    public static void parseDocument(String parseId) throws Exception {
//        // 使用默认凭证初始化Credentials Client。
//        Config config = new Config()
//                // 通过credentials获取配置中的AccessKey ID
//                .setAccessKeyId(accessKeyId)
//                // 通过credentials获取配置中的AccessKey Secret
//                .setAccessKeySecret(accessKeySecret);
//        // 访问的域名，支持ipv4和ipv6两种方式，ipv6请使用docmind-api-dualstack.cn-hangzhou.aliyuncs.com
//        config.endpoint = "docmind-api.cn-hangzhou.aliyuncs.com";
//        Client client = new Client(config);
//
//        int layoutNum = 0;
//        int layoutStepSize = 100;
//        boolean hasMore = true;
//
//        while (hasMore) {
//            GetDocParserResultRequest resultRequest = new GetDocParserResultRequest();
//            resultRequest.id = parseId;
//            resultRequest.layoutStepSize = layoutStepSize;
//            resultRequest.layoutNum = layoutNum;
//
//            GetDocParserResultResponse response = client.getDocParserResult(resultRequest);
//            if (response.getStatusCode() == 200) {
//                GetDocParserResultResponseBody body = response.getBody();
//                Map<String, ?> data = body.getData();
//
//                // 处理当前批次的数据
//                processDocumentData(data);
//
//                // 检查是否还有更多数据
//                // 根据阿里云文档，需要检查返回的数据判断是否继续
//                Object layoutsObj = data.get("layouts");
//                if (layoutsObj instanceof List<?>) {
//                    List<?> layouts = (List<?>) layoutsObj;
//                    if (layouts.isEmpty() || layouts.size() < layoutStepSize) {
//                        hasMore = false;
//                    } else {
//                        layoutNum += layoutStepSize;
//                    }
//                } else {
//                    hasMore = false;
//                }
//            } else {
//                System.err.println("获取文档解析结果失败，状态码: " + response.getStatusCode());
//                hasMore = false;
//            }
//        }
//    }

    /**
     * 处理文档解析数据
     */
    private static void processDocumentData(Map<String, ?> data) {
        if (data == null) {
            return;
        }

        // 输出完整的数据结构供查看
        System.out.println("文档解析结果: " + JSON.toJSONString(data));

        // 可以进一步处理具体的文档内容，如提取文本、表格、图片等
        Object layoutsObj = data.get("layouts");
        if (layoutsObj instanceof List) {
            List<?> layouts = (List<?>) layoutsObj;
            for (Object layoutObj : layouts) {
                if (layoutObj instanceof Map) {
                    Map<?, ?> layout = (Map<?, ?>) layoutObj;
                    String type = (String) layout.get("type");
                    String text = (String) layout.get("text");
                    String markdownContent = (String) layout.get("markdownContent");

                    System.out.println("类型: " + type);
                    System.out.println("文本: " + text);
                    System.out.println("Markdown内容: " + markdownContent);
                    System.out.println("-------------------");
                }
            }
        }
    }

    /**
     * 使用阿里云文档解析服务解析文件
     */
    public static String parseFileWithAliyun(String parseId, String documentType) throws Exception {
        String documentContent = "";

        // 2. 轮询查询解析状态直到完成
        String status = "";
        do {
            Thread.sleep(5000); // 等待5秒后查询
            status = getClJg(parseId);
            log.info("文档解析状态: " + status);
            if ("Fail".equals(status)) {
                throw new Exception("文档解析失败，任务ID: " + parseId);
            }
        } while (!"success".equals(status));

        // 3. 获取解析结果
        documentContent = getDocumentContent(parseId, documentType);

        return documentContent;
    }

    /**
     * 获取文档解析内容
     *
     * @param parseId 解析任务ID
     * @return 文档内容
     * @throws Exception 异常
     */
    private static String getDocumentContent(String parseId, String documentType) throws Exception {
        Config config = new Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);
        config.endpoint = "docmind-api.cn-hangzhou.aliyuncs.com";
        config.readTimeout = 60000;
        config.connectTimeout = 10000;
        Client client = new Client(config);

        int maxRetries = 3;
        int retryCount = 0;

        StringBuilder contentBuilder = new StringBuilder();

        // 初始步长
        int layoutStepSize = 300;
        int layoutNum = 0;
        boolean hasMore = true;

        while (retryCount < maxRetries) {
            try {
                while (hasMore) {
                    GetDocParserResultRequest resultRequest = new GetDocParserResultRequest();
                    resultRequest.id = parseId;
                    resultRequest.layoutStepSize = layoutStepSize;
                    resultRequest.layoutNum = layoutNum;

                    GetDocParserResultResponse response = client.getDocParserResult(resultRequest);
                    if (response.getStatusCode() == 200) {
                        GetDocParserResultResponseBody body = response.getBody();
                        String code = body.getCode();
                        String message = body.getMessage();
                        if ("DocParserResultTooLarge".equals(code)) {
                            // 如果返回 DocParserResultTooLarge，减小步长并重试
                            layoutStepSize = Math.max(10, layoutStepSize / 2); // 减小一半，但至少为10
                            log.warn("文档解析结果过大，减小步长到: {}", layoutStepSize);
                            continue;
                        }
                        Map<String, ?> data = body.getData();
                        // 处理当前批次的数据
                        if ("4".equals(documentType)) {
                            contentBuilder.append(extractVideoFromData(data));
                            // 检查是否还有更多数据
                            Object segmentsObj = data.get("segments");
                            if (segmentsObj instanceof List<?>) {
                                List<?> segments = (List<?>) segmentsObj;
                                if (segments.isEmpty() || segments.size() < layoutStepSize) {
                                    hasMore = false;
                                } else {
                                    layoutNum += layoutStepSize;
                                }
                            } else {
                                hasMore = false;
                            }
                        } else {
                            contentBuilder.append(extractTextFromData(data));
                            // 检查是否还有更多数据
                            Object layoutsObj = data.get("layouts");
                            if (layoutsObj instanceof List<?>) {
                                List<?> layouts = (List<?>) layoutsObj;
                                if (layouts.isEmpty() || layouts.size() < layoutStepSize) {
                                    hasMore = false;
                                } else {
                                    layoutNum += layoutStepSize;
                                }
                            } else {
                                hasMore = false;
                            }
                        }

                        // 继续下一次循环，使用新的步长
                    } else {
                        throw new Exception("获取文档解析结果失败，状态码: " + response.getStatusCode() + ", 消息: " + response.getBody().getMessage());
                    }
                }

                return contentBuilder.toString();
            } catch (Exception e) {
                retryCount++;
                if (retryCount >= maxRetries) {
                    throw e;
                }
                Thread.sleep(1000 * retryCount);
            }
        }

        throw new Exception("获取文档解析结果失败，达到最大重试次数");
    }


    /**
     * 从视频解析数据中提取内容
     *
     * @param data 解析数据
     * @return 提取的视频内容
     */
    private static String extractVideoFromData(Map<String, ?> data) {
        StringBuilder content = new StringBuilder();

        // 获取 segments 数据
        Object segmentsObj = data.get("segments");
        if (segmentsObj instanceof List) {
            List<?> segments = (List<?>) segmentsObj;

            for (Object segmentObj : segments) {
                if (segmentObj instanceof Map) {
                    Map<?, ?> segment = (Map<?, ?>) segmentObj;

                    // 获取索引
                    Object indexObj = segment.get("index");
                    if (indexObj != null) {
                        content.append("片段 ").append(indexObj).append(":\n");
                    }

                    // 处理音频帧信息
                    Object audioFramesObj = segment.get("audio_frames");
                    if (audioFramesObj instanceof List) {
                        List<?> audioFrames = (List<?>) audioFramesObj;
                        for (Object audioFrameObj : audioFrames) {
                            if (audioFrameObj instanceof Map) {
                                Map<?, ?> audioFrame = (Map<?, ?>) audioFrameObj;
                                Object asrInfo = audioFrame.get("ASR_info");
                                if (asrInfo != null) {
                                    content.append("音频内容: ").append(asrInfo.toString()).append("\n");
                                }
                            }
                        }
                    }

                    // 处理视频帧信息
                    Object videoFramesObj = segment.get("video_frames");
                    if (videoFramesObj instanceof List) {
                        List<?> videoFrames = (List<?>) videoFramesObj;
                        for (Object videoFrameObj : videoFrames) {
                            if (videoFrameObj instanceof Map) {
                                Map<?, ?> videoFrame = (Map<?, ?>) videoFrameObj;
                                Object textInfo = videoFrame.get("text_info");
                                if (textInfo != null) {
                                    content.append("画面描述: ").append(textInfo.toString()).append("\n");
                                }
                            }
                        }
                    }

                    content.append("\n");
                }
            }
        }

        return content.toString();
    }

    /**
     * 从解析数据中提取文本内容
     *
     * @param data 解析数据
     * @return 提取的文本内容
     */
    private static String extractTextFromData(Map<String, ?> data) {
        StringBuilder content = new StringBuilder();

        Object layoutsObj = data.get("layouts");
        if (layoutsObj instanceof List) {
            List<?> layouts = (List<?>) layoutsObj;
            for (Object layoutObj : layouts) {
                if (layoutObj instanceof Map) {
                    Map<?, ?> layout = (Map<?, ?>) layoutObj;
                    String type = (String) layout.get("type");
                    String text = (String) layout.get("markdownContent");

                    System.out.println("类型: " + type);
                    System.out.println("text: " + text);
                    // 只提取文本类型的内容
                    if (StringUtils.isNotEmpty(text)) {
                        content.append(text).append("\n");
                    }
                }
            }
        }

        return content.toString();
    }


    public static void main(String[] args) {
        try {
//            AliYunFileParserUtils.submitDocParserJob("D:\\kk.pdf", "kk.pdf");
            //docmind-20251014-188ee797e8584a2ea20dad5f460719f6
//            AliYunFileParserUtils.getClJg("docmind-20251014-188ee797e8584a2ea20dad5f460719f6");
            //AliYunFileParserUtils.parseDocument("docmind-20251014-188ee797e8584a2ea20dad5f460719f6");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

